import 'package:x3_base_core/base_enums/base_date_type_enum.dart';

class BaseDateUtil {
  BaseDateUtil._();

  /// 根据传入时间计算该时间是其年份的第几周,默认date为DateTime.now()
  static int weekOfYear({DateTime date}) {
    // 一天的毫秒值
    int dayMills = 24 * 60 * 60 * 1000;

    DateTime _dateTime;
    if (date != null) _dateTime = DateTime(date.year, date.month, date.day);
    if (date == null) {
      DateTime _now = DateTime.now();
      _dateTime = DateTime(_now.year, _now.month, _now.day);
    }
    //当前年份的第一天
    DateTime yearDateTime = DateTime(_dateTime.year, 1, 1, 0, 0, 0, 0);
    //当前年份是所有的时间戳(毫秒级)
    int targetTimeStamp = _dateTime.millisecondsSinceEpoch - yearDateTime.millisecondsSinceEpoch + dayMills;
    //当前共过了年的多少天
    int daySum = (targetTimeStamp / dayMills * 1.00).toInt();
    //weekOfYear
    int woy = 0;
    if (_dateTime.weekday != 7) {
      daySum = daySum - _dateTime.weekday;
      //加上最后一周
      woy += 1;
    }
    double woyDouble = daySum / 7;
    if (woyDouble.remainder(1) == 0.0) {
      woy += woyDouble.toInt();
    } else {
      //加上第一周
      woy += woyDouble.toInt();
      woy += 1;
    }
    return woy;
  }

  /// 根据year年的第week周，查询该周的开始和截止日期
  static List<DateTime> weekToDayFormat(int week, {int year = -2}) {
    // 一天的毫秒值
    int dayMills = 24 * 60 * 60 * 1000;
    // 一周的毫秒值
    int weekMills = 7 * dayMills;
    // year的第一天
    DateTime yearDateTime;
    if (year == -2) {
      DateTime _now = DateTime.now();
      yearDateTime = DateTime(_now.year, 1, 1);
    } else {
      yearDateTime = DateTime(year, 1, 1);
    }

    //目标周的毫秒时间戳
    int targetTimeStamp = yearDateTime.millisecondsSinceEpoch + (week * 7 - yearDateTime.weekday) * dayMills;
    DateTime start = DateTime.fromMillisecondsSinceEpoch(targetTimeStamp - weekMills + dayMills);
    DateTime end = DateTime.fromMillisecondsSinceEpoch(targetTimeStamp + dayMills - 1);
    if (start.year != end.year) {
      //跨年了
      if (start.year == yearDateTime.year) {
        end = DateTime(yearDateTime.year, 12, 31, 23, 59, 59, 999);
      }
      if (end.year == yearDateTime.year) {
        start = DateTime(yearDateTime.year, 1, 1);
      }
    }
    return [start, end];
  }

  ///获取星期几
  static String getTheWeekDate(int weekDay) {
    if (weekDay == null) return "";

    switch (weekDay) {
      case 1:
        return "周一";
        break;
      case 2:
        return "周二";
        break;
      case 3:
        return "周三";
        break;
      case 4:
        return "周四";
        break;
      case 5:
        return "周五";
        break;
      case 6:
        return "周六";
        break;
      case 7:
        return "周日";
        break;
      default:
        return "";
    }
  }

  /// 获取当前标签
  static String getCurrLabel(DateTime start, DateTime end) {
    // 校验今天
    bool checkToday = itIsToday(start, end);
    if (checkToday) return "今天";
    // 校验昨天
    bool checkYesterday = itIsYesterday(start, end);
    if (checkYesterday) return "昨天";

    // 校验本周
    bool checkCurrWeek = itIsCurrWeek(start, end);
    if (checkCurrWeek) return "本周";
    // 校验上周
    bool checkLastWeek = itIsLastWeek(start, end);
    if (checkLastWeek) return "上周";

    // 校验本月
    bool checkCurrMonth = itIsCurrMonth(start, end);
    if (checkCurrMonth) return "本月";
    // 校验上个月
    bool checkLastMonth = itIsLastMonth(start, end);
    if (checkLastMonth) return "上月";

    // 校验今年
    bool checkCurrYear = itIsCurrYear(start, end);
    if (checkCurrYear) return "今年";
    // 校验去年
    bool checkLastYear = itIsLastYear(start, end);
    if (checkLastYear) return "去年";
    return '自定义';
  }

  /// 根据枚举获取对应标签
  static String getCurrLabelForDateTypeEnum(BaseDateTypeEnum typeEnum) {
    switch (typeEnum) {
      case BaseDateTypeEnum.today:
        return '今天';
        break;
      case BaseDateTypeEnum.yesterday:
        return '昨天';
        break;
      case BaseDateTypeEnum.week:
        return '本周';
        break;
      case BaseDateTypeEnum.lastWeek:
        return '上周';
        break;
      case BaseDateTypeEnum.month:
        return '本月';
        break;
      case BaseDateTypeEnum.lastMonth:
        return '上月';
        break;
      case BaseDateTypeEnum.year:
        return '今年';
        break;
      case BaseDateTypeEnum.lastYear:
        return '去年';
        break;
      case BaseDateTypeEnum.customize:
        return '自定义';
        break;
      default:
        return '';
        break;
    }
  }

  /// 根据标签获取对应枚举
  static BaseDateTypeEnum getCurrDateTypeEnumForLabel(String label) {
    switch (label) {
      case "今天":
        return BaseDateTypeEnum.today;
        break;
      case "昨天":
        return BaseDateTypeEnum.yesterday;
        break;
      case "本周":
        return BaseDateTypeEnum.week;
        break;
      case '上周':
        return BaseDateTypeEnum.lastWeek;
        break;
      case '本月':
        return BaseDateTypeEnum.month;
        break;
      case "上月":
        return BaseDateTypeEnum.lastMonth;
        break;
      case "本年":
        return BaseDateTypeEnum.year;
        break;
      case "今年":
        return BaseDateTypeEnum.year;
        break;
      case "去年":
        return BaseDateTypeEnum.lastYear;
        break;
      case '自定义':
        return BaseDateTypeEnum.customize;
        break;
      default:
        return null;
        break;
    }
  }

  /// 获取当前时间枚举标签
  static BaseDateTypeEnum getCurrDateTypeEnum(DateTime start, DateTime end) {
    // 校验今天
    bool checkToday = itIsToday(start, end);
    if (checkToday) return BaseDateTypeEnum.today;
    // 校验昨天
    bool checkYesterday = itIsYesterday(start, end);
    if (checkYesterday) return BaseDateTypeEnum.yesterday;

    // 校验本周
    bool checkCurrWeek = itIsCurrWeek(start, end);
    if (checkCurrWeek) return BaseDateTypeEnum.week;
    // 校验上周
    bool checkLastWeek = itIsLastWeek(start, end);
    if (checkLastWeek) return BaseDateTypeEnum.lastWeek;

    // 校验本月
    bool checkCurrMonth = itIsCurrMonth(start, end);
    if (checkCurrMonth) return BaseDateTypeEnum.month;
    // 校验上个月
    bool checkLastMonth = itIsLastMonth(start, end);
    if (checkLastMonth) return BaseDateTypeEnum.lastMonth;

    // 校验本年
    bool checkCurrYear = itIsCurrYear(start, end);
    if (checkCurrYear) return BaseDateTypeEnum.year;
    // 校验上年
    bool checkLastYear = itIsLastYear(start, end);
    if (checkLastYear) return BaseDateTypeEnum.lastYear;
    return BaseDateTypeEnum.customize;
  }

  /// 获取标签对应的时间段
  static List<DateTime> getTimePeriodForDateTypeEnum(BaseDateTypeEnum typeEnum) {
    switch (typeEnum) {
      case BaseDateTypeEnum.today:
        return getToday();
        break;
      case BaseDateTypeEnum.yesterday:
        return getYesterday();
        break;
      case BaseDateTypeEnum.week:
        return getCurrWeek();
        break;
      case BaseDateTypeEnum.lastWeek:
        return getLastWeek();
        break;
      case BaseDateTypeEnum.month:
        return getCurrMonth();
        break;
      case BaseDateTypeEnum.lastMonth:
        return getLastMonth();
        break;
      case BaseDateTypeEnum.year:
        return getCurrYear();
        break;
      case BaseDateTypeEnum.lastYear:
        return getLastYear();
        break;
      case BaseDateTypeEnum.customize:
        return [];
      default:
        return [];
        break;
    }
  }

  /// 获取'今天'
  static List<DateTime> getToday() {
    DateTime nowDate = DateTime.now();
    DateTime start = DateTime(nowDate.year, nowDate.month, nowDate.day);
    DateTime end = DateTime(nowDate.year, nowDate.month, nowDate.day, 23, 59, 59);
    return [start, end];
  }

  /// 获取'昨天'
  static List<DateTime> getYesterday() {
    DateTime nowDate = DateTime.now();
    DateTime yesterday = nowDate.subtract(Duration(days: 1));
    DateTime start = DateTime(yesterday.year, yesterday.month, yesterday.day);
    DateTime end = DateTime(yesterday.year, yesterday.month, yesterday.day, 23, 59, 59);
    return [start, end];
  }

  /// 获取某天
  /// 根据年、月、日获取该日的开始和结束
  static List<DateTime> getSomeDay(int year, int month, int day) {
    DateTime start = DateTime(year, month, day);
    DateTime end = DateTime(year, month, day, 23, 59, 59);
    return [start, end];
  }

  /// 获取'本周'
  static List<DateTime> getCurrWeek() {
    DateTime nowDate = DateTime.now();
    DateTime start;
    DateTime end;
    int week = nowDate.weekday;
    if (week == 1) {
      DateTime monday = DateTime(nowDate.year, nowDate.month, nowDate.day);
      DateTime sunday = monday.add(Duration(days: 6));
      start = DateTime(monday.year, monday.month, monday.day);
      end = DateTime(sunday.year, sunday.month, sunday.day, 23, 59, 59);
    }
    if (week == 7) {
      DateTime sunday = DateTime(nowDate.year, nowDate.month, nowDate.day);
      DateTime monday = sunday.subtract(Duration(days: 6));
      start = DateTime(monday.year, monday.month, monday.day);
      end = DateTime(sunday.year, sunday.month, sunday.day, 23, 59, 59);
    }
    if (week != 1 && week != 7) {
      DateTime monday = nowDate.subtract(Duration(days: week - 1));
      DateTime sunday = nowDate.add(Duration(days: 7 - week));
      start = DateTime(monday.year, monday.month, monday.day);
      end = DateTime(sunday.year, sunday.month, sunday.day, 23, 59, 59);
    }
    assert(start != null);
    assert(end != null);
    return [start, end];
  }

  /// 获取'上周'
  static List<DateTime> getLastWeek() {
    DateTime nowDate = DateTime.now();
    // 上周的当日 当前减去7天
    DateTime dayOfLastWeek = nowDate.subtract(Duration(days: 7));
    DateTime start;
    DateTime end;
    int week = dayOfLastWeek.weekday;
    if (week == 1) {
      DateTime monday = DateTime(dayOfLastWeek.year, dayOfLastWeek.month, dayOfLastWeek.day);
      DateTime sunday = monday.add(Duration(days: 6));
      start = DateTime(monday.year, monday.month, monday.day);
      end = DateTime(sunday.year, sunday.month, sunday.day, 23, 59, 59);
    }
    if (week == 7) {
      DateTime sunday = DateTime(dayOfLastWeek.year, dayOfLastWeek.month, dayOfLastWeek.day);
      DateTime monday = sunday.subtract(Duration(days: 6));
      start = DateTime(monday.year, monday.month, monday.day);
      end = DateTime(sunday.year, sunday.month, sunday.day, 23, 59, 59);
    }
    if (week != 1 && week != 7) {
      DateTime monday = dayOfLastWeek.subtract(Duration(days: week - 1));
      DateTime sunday = dayOfLastWeek.add(Duration(days: 7 - week));
      start = DateTime(monday.year, monday.month, monday.day);
      end = DateTime(sunday.year, sunday.month, sunday.day, 23, 59, 59);
    }
    assert(start != null);
    assert(end != null);
    return [start, end];
  }

  /// 获取该周的开始和结束
  static List<DateTime> getSomeWeek(int year, int weekIndex) {
    return weekToDayFormat(weekIndex, year: year);
  }

  /// 获取该年有多少周
  static int getWeeksThereAreInTheYear(int year) {
    // 本年的最后一天
    DateTime laseDayOfTheYear = DateTime(year + 1, 1, 1).subtract(Duration(days: 1));
    return weekOfYear(date: laseDayOfTheYear);
  }

  /// 获取某年的全部周
  static List<List<DateTime>> getAllWeeksOfAYear(int year) {
    int sum = getWeeksThereAreInTheYear(year);
    List<List<DateTime>> allWeek = List.generate(sum, (index) => getSomeWeek(year, index + 1));
    return allWeek;
  }

  /// 获取本月
  static List<DateTime> getCurrMonth() {
    DateTime nowDate = DateTime.now();
    // 下个月的第一天
    DateTime firstDayOfNextMonth = DateTime(nowDate.year, nowDate.month + 1, 1);
    // 这个月的最后一天
    DateTime lastDayOfCurrMonth = firstDayOfNextMonth.subtract(Duration(days: 1));
    // 这个月的第一天
    DateTime firstDayOfCurrMonth = DateTime(nowDate.year, nowDate.month, 1);
    DateTime start = DateTime(firstDayOfCurrMonth.year, firstDayOfCurrMonth.month, firstDayOfCurrMonth.day);
    DateTime end = DateTime(lastDayOfCurrMonth.year, lastDayOfCurrMonth.month, lastDayOfCurrMonth.day, 23, 59, 59);
    return [start, end];
  }

  /// 获取上个月
  static List<DateTime> getLastMonth() {
    DateTime nowDate = DateTime.now();
    // 上个月的最后一天
    DateTime lastDayOfLastMonth = DateTime(nowDate.year, nowDate.month, 1).subtract(Duration(days: 1));
    // 上个月的第一天
    DateTime firstDayOfLastMonth = DateTime(lastDayOfLastMonth.year, lastDayOfLastMonth.month, 1);
    DateTime start = DateTime(firstDayOfLastMonth.year, firstDayOfLastMonth.month, firstDayOfLastMonth.day);
    DateTime end = DateTime(lastDayOfLastMonth.year, lastDayOfLastMonth.month, lastDayOfLastMonth.day, 23, 59, 59);
    return [start, end];
  }

  /// 获取某月
  /// 根据年、月，获取某月的开始和结束
  static List<DateTime> getSomeMonth(int year, int month) {
    // 下个月的第一天
    DateTime firstDayOfNextMonth = DateTime(year, month + 1, 1);
    // 该月的最后一天
    DateTime lastDayOfTheMonth = firstDayOfNextMonth.subtract(Duration(days: 1));
    DateTime start = DateTime(year, month, 1);
    DateTime end = DateTime(lastDayOfTheMonth.year, lastDayOfTheMonth.month, lastDayOfTheMonth.day, 23, 59, 59);
    return [start, end];
  }

  /// 获取今年
  static List<DateTime> getCurrYear() {
    DateTime nowDate = DateTime.now();
    // 今年第一天
    DateTime firstDayOfCurrYear = DateTime(nowDate.year, 1, 1);
    // 明年的第一天
    DateTime lastDayOfNextYear = DateTime(nowDate.year + 1, 1, 1);
    // 今年的最后一天
    DateTime lastDayOfCurrYear = lastDayOfNextYear.subtract(Duration(days: 1));
    DateTime start = DateTime(firstDayOfCurrYear.year, firstDayOfCurrYear.month, firstDayOfCurrYear.day);
    DateTime end = DateTime(lastDayOfCurrYear.year, lastDayOfCurrYear.month, lastDayOfCurrYear.day, 23, 59, 59);
    return [start, end];
  }

  /// 获取去年
  static List<DateTime> getLastYear() {
    DateTime nowDate = DateTime.now();
    // 今年第一天
    DateTime firstDayOfCurrYear = DateTime(nowDate.year, 1, 1);
    // 去年的最后一天
    DateTime lastDayOfLastYear = firstDayOfCurrYear.subtract(Duration(days: 1));
    // 去年的第一天
    DateTime firstDayOfLastYear = DateTime(lastDayOfLastYear.year, 1, 1);
    DateTime start = DateTime(firstDayOfLastYear.year, firstDayOfLastYear.month, firstDayOfLastYear.day);
    DateTime end = DateTime(lastDayOfLastYear.year, lastDayOfLastYear.month, lastDayOfLastYear.day, 23, 59, 59);
    return [start, end];
  }

  /// 获取某年的开始和结束
  static List<DateTime> getSomeYear(int year) {
    // 下个年的第一天
    DateTime firstDayOfNextYear = DateTime(year + 1, 1, 1);
    // 该年的最后一天
    DateTime lastDayOfTheYear = firstDayOfNextYear.subtract(Duration(days: 1));
    DateTime start = DateTime(year, 1, 1);
    DateTime end = DateTime(lastDayOfTheYear.year, lastDayOfTheYear.month, lastDayOfTheYear.day, 23, 59, 59);
    return [start, end];
  }

  /// 判断是否是今天
  static bool itIsToday(DateTime start, DateTime end) {
    DateTime nowDate = DateTime.now();
    if (start.year != end.year) return false;
    if (start.month != end.month) return false;
    if (start.day != end.day) return false;
    if (start.year != nowDate.year) return false;
    if (start.month != nowDate.month) return false;
    if (start.day != nowDate.day) return false;
    return true;
  }

  /// 判断是否是昨天
  static bool itIsYesterday(DateTime start, DateTime end) {
    DateTime nowDate = DateTime.now();
    if (start.year != end.year) return false;
    if (start.month != end.month) return false;
    if (start.day != end.day) return false;
    DateTime yesterday = nowDate.subtract(Duration(days: 1));
    if (start.year != yesterday.year) return false;
    if (start.month != yesterday.month) return false;
    if (start.day != yesterday.day) return false;
    return true;
  }

  /// 判断是否是本周
  static bool itIsCurrWeek(DateTime start, DateTime end) {
    List<DateTime> weekList = getCurrWeek();
    return compareDateTimeList(weekList, [start, end]);
  }

  /// 判断是否是上周
  static bool itIsLastWeek(DateTime start, DateTime end) {
    List<DateTime> lastWeekList = getLastWeek();
    return compareDateTimeList(lastWeekList, [start, end]);
  }

  /// 判断是否是当月
  static bool itIsCurrMonth(DateTime start, DateTime end) {
    List<DateTime> currMonthList = getCurrMonth();
    return compareDateTimeList(currMonthList, [start, end]);
  }

  /// 判断是否是上个月
  static bool itIsLastMonth(DateTime start, DateTime end) {
    List<DateTime> lastMonthList = getLastMonth();
    return compareDateTimeList(lastMonthList, [start, end]);
  }

  /// 判断是否是今年
  static bool itIsCurrYear(DateTime start, DateTime end) {
    List<DateTime> currYearList = getCurrYear();
    return compareDateTimeList(currYearList, [start, end]);
  }

  /// 判断是否是去年
  static bool itIsLastYear(DateTime start, DateTime end) {
    List<DateTime> lastYearList = getLastYear();
    return compareDateTimeList(lastYearList, [start, end]);
  }

  /// 比较前后两个DateTime 数组对应位置的时间的年月日是否一致
  static bool compareDateTimeList(List<DateTime> before, List<DateTime> after) {
    if (after.length != before.length) return false;
    int index = 0;
    while (index < after.length) {
      bool compare = compareDateTime(after[index], before[index]);
      if (!compare) return false;
      index++;
    }
    return true;
  }

  /// 比较两个DateTime的年月日是否相同
  static bool compareDateTime(DateTime a, DateTime b) {
    if (a == null) return false;
    if (b == null) return false;
    if (a.year != b.year) return false;
    if (a.month != b.month) return false;
    if (a.day != b.day) return false;
    return true;
  }

  /// 将时间加上时区字段（+0800）
  /// 可以传入 DateTime/String
  static String dateTimeAddTimeZone(date) {
    if (date == null) return '';
    if (date is String && date.contains("+0800")) return date;
    if (!(date is DateTime) && !(date is String)) return '';
    if (date is DateTime) return date.toIso8601String() + '+0800';
    if (date is String) {
      DateTime daTime = DateTime.tryParse(date);
      if (daTime == null) return '';
      return daTime.toIso8601String() + '+0800';
    }
    return '';
  }

  /// 将时间加上时区字段（+0800）
  static List<String> dateListAddTimeZone(List<dynamic> dateList) {
    if (dateList == null || dateList.isEmpty) return [];
    List<String> dList = [];
    dateList.forEach((element) {
      String date = dateTimeAddTimeZone(element);
      dList.add(date);
    });
    return dList;
  }
}
